package com.tengju.user.infrastructure.repository.convert;

import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.collect.Lists;
import com.tengju.user.domain.model.protocol.ProtocolVersion;
import com.tengju.user.domain.model.user.*;
import com.tengju.user.domain.shared.DateUtil;
import com.tengju.user.domain.shared.IdObject;
import com.tengju.user.domain.shared.JsonUtil;
import com.tengju.user.infrastructure.persistence.mybatis.dataobject.StarChangeRecordDO;
import com.tengju.user.infrastructure.persistence.mybatis.dataobject.UserInfoDO;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.Optional;

public class UserConvert {

    private UserConvert() {
    }

    public static UserIdCode decryptIdCode(Long encryptIdCode) {
        if (encryptIdCode != null) {
            return new UserIdCode((encryptIdCode >> 16) - 202111);
        }
        return null;
    }

    public static Long encryptIdCode(UserIdCode idCode) {
        if (idCode != null) {
            return (idCode.getValue() + 202111) << 16;
        }
        return null;
    }

    public static void main(String[] args) {
        System.out.println(encryptIdCode(new UserIdCode(200037)));
    }

    public static UserInfo convertUserDOToUser(UserInfoDO userInfoDO) {
        if (userInfoDO == null) {
            return null;
        }
        List<ProtocolVersion> protocolInfo = Lists.newArrayList();
        if (!StringUtils.isEmpty(userInfoDO.getProtocolInfo())) {
            protocolInfo = JsonUtil.toList(userInfoDO.getProtocolInfo(), new TypeReference<>() {
            });
        }
        return new UserInfo(
                new UserId(userInfoDO.getUserId()),
                userInfoDO.getIdCode() == null ? null : decryptIdCode(userInfoDO.getIdCode()),
                userInfoDO.getAreaCode(),
                userInfoDO.getMobile(),
                userInfoDO.getName(),
                userInfoDO.getNickname(),
                userInfoDO.getStarRole(),
                userInfoDO.getStarLevel(),
                userInfoDO.getParentIdCode() == null ? null : decryptIdCode(userInfoDO.getParentIdCode()),
                userInfoDO.getCountry(),
                userInfoDO.getCity(),
                Sex.fromVal(userInfoDO.getSex()),
                userInfoDO.getHeadImage(),
                protocolInfo
                );
    }


    public static UserInfoDO convertUserInfoToDO(UserInfo userInfo) {

        String protocolInfo = null;
        if (!CollectionUtils.isEmpty(userInfo.getProtocolInfo())) {
            protocolInfo = JsonUtil.toJSONString(userInfo.getProtocolInfo());
        }

        UserInfoDO userInfoDO = new UserInfoDO();
        userInfoDO.setUserId(Optional.ofNullable(userInfo.getUserId()).map(IdObject::getValue).orElse(null));
        userInfoDO.setIdCode(Optional.ofNullable(userInfo.getIdCode())
                .map(UserConvert::encryptIdCode)
                .orElse(null));
        userInfoDO.setAreaCode(userInfo.getAreaCode());
        userInfoDO.setMobile(userInfo.getMobile());
        userInfoDO.setName(userInfo.getName());
        userInfoDO.setNickname(userInfo.getNickName());
        userInfoDO.setStarRole(userInfo.getStarRole());
        userInfoDO.setStarLevel(userInfo.getStarLevel());
        userInfoDO.setParentIdCode(Optional.ofNullable(userInfo.getPidCode())
                .map(UserConvert::encryptIdCode)
                .orElse(null));
        userInfoDO.setCountry(userInfo.getCountry());
        userInfoDO.setCity(userInfo.getCity());
        userInfoDO.setSex(Optional.ofNullable(userInfo.getSex()).map(Sex::getVal).orElse(null));
        userInfoDO.setHeadImage(userInfo.getHeadImage());
        userInfoDO.setProtocolInfo(protocolInfo);

        return userInfoDO;
    }

    public static StarChangeRecordDO convertStarChangeRecordToDO(StarChangeRecord starChangeRecord) {
        Date now = new Date();
        StarChangeRecordDO starChangeRecordDO = new StarChangeRecordDO();
        starChangeRecordDO.setAfterStarLevel(starChangeRecord.getAfterStarLevel());
        starChangeRecordDO.setAfterStarRole(starChangeRecord.getAfterStarRole());
        starChangeRecordDO.setBeforeStarLevel(starChangeRecord.getBeforeStarLevel());
        starChangeRecordDO.setBeforeStarRole(starChangeRecord.getBeforeStarRole());
        starChangeRecordDO.setChangeType(starChangeRecord.getChangeType().getCode());
        starChangeRecordDO.setIdCode(starChangeRecord.getIdCode().getValue());
        starChangeRecordDO.setOperBy(starChangeRecord.getOperBy());
        starChangeRecordDO.setUpdateTime(now);
        starChangeRecordDO.setCreateTime(now);
        return starChangeRecordDO;
    }

    public static StarChangeRecord convertStarChangeRecordDOToEntity(StarChangeRecordDO recordDO) {
        return new StarChangeRecord(
                new StarChangeRecordId(recordDO.getId()),
                UserIdCode.of(recordDO.getIdCode()),
                recordDO.getAfterStarRole(),
                recordDO.getAfterStarLevel(),
                recordDO.getBeforeStarRole(),
                recordDO.getBeforeStarLevel(),
                StarChangeTypeEnum.parseByCode(recordDO.getChangeType()),
                recordDO.getOperBy(),
                recordDO.getOperDesc(),
                DateUtil.dateToLocalDateTime(recordDO.getCreateTime())
        );
    }
}
